﻿#include "TelltaleCtrl/View/KEYL_TelltaleView.h"
#include "Common/HmiAdapterRuntime.h"
#include "Scene.h"
#include "Config.h"
#include "Video.h"
#include "SDL/SDL.h"
#include "ite/itp.h"
#include "log_api.h"
#include <assert.h>

extern ITUActionFunction actionFunctions[];

static struct PageUnite hmiPage = {
    .id_ = PAGE_OFF,
    .is_update_ = false,
    .mutex_ = PTHREAD_MUTEX_INITIALIZER,
};

#define MAX_STRARG_LEN 32

// scene
ITUScene theScene;
static SDL_Window *window;
static ITUSurface* screenSurf;
static int screenWidth;
static int screenHeight;
static uint64_t timestamp = 0;
static uint64_t timestampbase = 0;
static uint8_t  frame = 0;

static int LoadScene(void)
{
    uint32_t tick1, tick2;
    if (theScene.root)
    {
        ituSceneExit(&theScene);
    }

    // load itu file
    tick1 = SDL_GetTicks();
    int ret = ituSceneLoadFileCore(&theScene, g_theSceneConfig.ituXmlFilePath_);
    if(ret != 0)    // 0 is success
    {
        LOG_E("itu file not find : %s\n", g_theSceneConfig.ituXmlFilePath_);
        return -1;
    }
    else
    {
        tick2 = SDL_GetTicks();
        LOG_D("itu loading time: %dms\n", tick2 - tick1);
        
        tick1 = tick2;
        tick2 = SDL_GetTicks();
        LOG_D("itu init time: %dms\n", tick2 - tick1);

        // frame
        timestamp = SDL_GetTicks();
        timestampbase = timestamp;
        // frame
        return 0;
    }
    
}

#define PLAY_BOOT_VIDEO true

bool SceneInit(void)
{
    int ret = -1;
    bool result = false;
    do
    {
        ret = SDL_Init(SDL_INIT_VIDEO);
        if(ret < 0)
        {
            LOG_E("Couldn't initialize SDL: %s\n", SDL_GetError());
            result = false;
            break;
        }

        screenWidth = ithLcdGetWidth();
        screenHeight = ithLcdGetHeight();
        window = SDL_CreateWindow("Display Control Board", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, screenWidth, screenHeight, 0);
        if (!window)
        {
            LOG_E("Couldn't create window: %s\n", SDL_GetError());
            result = false;
            break;
        }

        InitConfig();
        // init itu
        ituLcdInit();
        ituM2dInit();
        ituSceneInit(&theScene, NULL);

        if(g_theSceneConfig.video_.isVideoVaild_)
        {
            ituFrameFuncInit();
            //play video
            PlayVideo(0, 0, ithLcdGetWidth(), ithLcdGetHeight(), 
                    CFG_BOOT_VIDEO_BGCOLOR, CFG_BOOT_VIDEO_VOLUME, g_theSceneConfig.video_.videoPath_);
        }

        screenSurf = ituGetDisplaySurface();
        ituFtInit();
        ituFtLoadFont(0, CFG_PRIVATE_DRIVE ":/font/" CFG_FONT_FILENAME, ITU_GLYPH_8BPP);
        ituSceneSetFunctionTable(&theScene, actionFunctions);

        //Init model
        TelltaleModelInit();
        MeterModelInit();

        ret = LoadScene();  
        if(ret != 0)
        {
            LOG_E("Couldn't load itu file: %s\n", g_theSceneConfig.ituXmlFilePath_);
            result = false;
            break;
        }

        //Load itu file          
        InitView(&g_KEYL_Telltale_ItuElement);
	    ReportViewVisible(&g_KEYL_Telltale_ItuElement);
        ituScenePreDraw(&theScene, screenSurf);

        //wait video finish
        if(g_theSceneConfig.video_.isVideoVaild_)
        {
            WaitPlayVideoFinish();
        }

        //start scene
        ituSceneStart(&theScene);

        result = true;

    } while (false);

    return result;
}

void SceneExit(void)
{
    MeterModelRelease();
    if (theScene.root)
    {
        ituSceneExit(&theScene);
    }
    ituFtExit();
    ituM2dExit();
    ituFrameFuncExit();
    SDL_DestroyWindow(window);

    SDL_Quit();
}

void SceneLoad(void)
{
    
}

static void updateScene(void)
{
    bool result = ituSceneUpdate(&theScene, ITU_EVENT_TIMER, 0, 0, 0);
    //printf("%d\n", result);
    if (result)
    {
        ituSceneDraw(&theScene, screenSurf);
        ituFlip(screenSurf);
    }
}

static uint8_t showFrameCount = 0;
static void updateFrame(void)
{
    timestamp = SDL_GetTicks();
	if(timestamp - timestampbase > 1000)
	{
		timestampbase = timestamp;
		frame++;
        showFrameCount++;
        if(showFrameCount > 60)
        {
		    LOG_A("frame : %d\n", frame);
            showFrameCount = 0;
        }
		frame = 0;
	}
	else
	{
		frame++;
    }
}

static void gotoNewLayer(const char* layerName)
{
    ITULayer* layer = ituSceneFindWidget(&theScene, layerName);
    if(layer)
    {    
        ituLayerGoto(layer);
    }
    else
    {
        LOG_W("unknow layer name:%d, ignore it!\n",layerName);
    }
}

static void updatePage()
{
    if(hmiPage.is_update_)
    {
        pthread_mutex_lock(&hmiPage.mutex_);
        switch (hmiPage.id_)
        {
            case PAGE_OFF:
            {
                gotoNewLayer("KEYL_Off");
                break;
            }

            case PAGE_MAIN:
            {
                gotoNewLayer("KEYL_Main");
                break;
            }

            case PAGE_BACKUP:
            {
                gotoNewLayer("KEYL_Backup");
                break;
            }
        
            default:
            {
                LOG_W("Unknown page id:%d, ignore it!\n", hmiPage.id_);
            }
        }
        hmiPage.is_update_ = false;
        pthread_mutex_unlock(&hmiPage.mutex_);
    }
}

void selectPage(enum HMI_PAGE pageId)
{
    switch (pageId)
    {
        case PAGE_OFF:
        case PAGE_MAIN:
        case PAGE_BACKUP:
        {
            pthread_mutex_lock(&hmiPage.mutex_);
            hmiPage.id_ = pageId;
            hmiPage.is_update_ = true;
            pthread_mutex_unlock(&hmiPage.mutex_);
            break;
        }
    
        default:
        {
            LOG_W("Unknown page id:%d, ignore it!\n", pageId);
            break;
        }
    }
}

int SceneRun(void)
{
    updatePage();
    TelltaleModelRun(); //update telltale models
    MeterModelRun();    //update meter models
    updateScene();      //refresh ui
    updateFrame();      //print frame
    return 0;
}

